#include <Arduino.h>
#include <string.h>
#include "display.h"
#include "animations.h"
#include "images.h"
#include "weather.h"

void wifi_search_anim(int x, int y)
{
  for (int i = 0; i < 4; i++)
  {
    displayManager->ShowMessage("WiFi", 5, displayManager->Color(255, 255, 255));
    switch (i)
    {
    case 3:
      displayManager->drawPixel(x, y, (uint32_t)0x22ff);
      displayManager->drawPixel(x + 1, y + 1, (uint32_t)0x22ff);
      displayManager->drawPixel(x + 2, y + 2, (uint32_t)0x22ff);
      displayManager->drawPixel(x + 3, y + 3, (uint32_t)0x22ff);
      displayManager->drawPixel(x + 2, y + 4, (uint32_t)0x22ff);
      displayManager->drawPixel(x + 1, y + 5, (uint32_t)0x22ff);
      displayManager->drawPixel(x, y + 6, (uint32_t)0x22ff);
    case 2:
      displayManager->drawPixel(x - 1, y + 2, (uint32_t)0x22ff);
      displayManager->drawPixel(x, y + 3, (uint32_t)0x22ff);
      displayManager->drawPixel(x - 1, y + 4, (uint32_t)0x22ff);
    case 1:
      displayManager->drawPixel(x - 3, y + 3, (uint32_t)0x22ff);
    case 0:
      break;
    }
    displayManager->show();
    delay(100);
    displayManager->clear();
  }
}

void wifi_check_anim(int x, int y)
{
  int wifiCheckTime = millis();
  int wifiCheckPoints = 0;
  displayManager->setTextColor(displayManager->Color(255, 255, 255));

  while (millis() - wifiCheckTime < 1500)
  {
    while (wifiCheckPoints < 7)
    {
      displayManager->ShowMessage("WiFi", 5, displayManager->Color(255, 255, 255));
      switch (wifiCheckPoints)
      {
      case 6:
        displayManager->drawPixel(x, y, displayManager->Color(0, 255, 0));
      case 5:
        displayManager->drawPixel(x - 1, y + 1, displayManager->Color(0, 255, 0));
      case 4:
        displayManager->drawPixel(x - 2, y + 2, displayManager->Color(0, 255, 0));
      case 3:
        displayManager->drawPixel(x - 3, y + 3, displayManager->Color(0, 255, 0));
      case 2:
        displayManager->drawPixel(x - 4, y + 4, displayManager->Color(0, 255, 0));
      case 1:
        displayManager->drawPixel(x - 5, y + 3, displayManager->Color(0, 255, 0));
      case 0:
        displayManager->drawPixel(x - 6, y + 2, displayManager->Color(0, 255, 0));
        break;
      }
      wifiCheckPoints++;
      displayManager->show();
      delay(100);
    }
  }
}

// 只用一次
static int wifi_search_anim_cont_x = DISPLAY_CONTENT_X_START_DEFAULT;
static int wifi_search_anim_icon_y = DISPLAY_ICON_Y_START_DEFAULT;
void wifi_search_anim_v2(const char *ssid, const char *ip)
{
  displayManager->clear();

  int nums = 10;
  char *tmp[nums] = {
      "1.", "SSID", WIFI_STA_SSID, "PWD", WIFI_STA_PWD,
      "2.", "visit", (char *)ip,
      "3.", "config~"};
  int offsets[nums] = {
      0, 6, 21, 91, 106,
      139, 145, 161,
      199, 205}; // 偏移量
  CRGB colors[nums] = {
      THEME_COLOR_DANGER,
      THEME_COLOR_TEXT,
      THEME_COLOR_SUCCESS,
      THEME_COLOR_TEXT,
      THEME_COLOR_SUCCESS,
      THEME_COLOR_DANGER,
      THEME_COLOR_TEXT,
      THEME_COLOR_SUCCESS,
      THEME_COLOR_DANGER,
      THEME_COLOR_TEXT,
  };
  displayManager->PrintAnimation(tmp,
                                 DISPLAY_CONTENT_X_START_DEFAULT, DISPLAY_CONTENT_X_END_DEFAULT,
                                 &wifi_search_anim_cont_x, offsets, colors, nums);

  displayManager->DrawIconAnimation(0, (int16_t *)&wifi_search_anim_icon_y, DISPLAY_ICON_Y_END_DEFAULT, &img_config);

  displayManager->show();
}

// 只用一次
static int wifi_check_anim_cont_x = DISPLAY_CONTENT_X_START_DEFAULT;
static int wifi_check_anim_icon_y = DISPLAY_ICON_Y_START_DEFAULT;
void wifi_check_anim_v2(const char *ssid, const char *ip)
{
  displayManager->clear();
  int wifiCheckTime = millis();
  int wifiCheckPoints = 0;

  displayManager->DrawIcon(0, 0, &img_info_success);

  int check_x = 31, check_y = 1;
  while (millis() - wifiCheckTime < 1500)
  {
    while (wifiCheckPoints < 7)
    {
      displayManager->Print("WiFi", 11, 5, CRGB::White);
      switch (wifiCheckPoints)
      {
      case 6:
        displayManager->drawPixel(check_x, check_y, displayManager->Color(0, 255, 0));
      case 5:
        displayManager->drawPixel(check_x - 1, check_y + 1, displayManager->Color(0, 255, 0));
      case 4:
        displayManager->drawPixel(check_x - 2, check_y + 2, displayManager->Color(0, 255, 0));
      case 3:
        displayManager->drawPixel(check_x - 3, check_y + 3, displayManager->Color(0, 255, 0));
      case 2:
        displayManager->drawPixel(check_x - 4, check_y + 4, displayManager->Color(0, 255, 0));
      case 1:
        displayManager->drawPixel(check_x - 5, check_y + 3, displayManager->Color(0, 255, 0));
      case 0:
        displayManager->drawPixel(check_x - 6, check_y + 2, displayManager->Color(0, 255, 0));
        break;
      }
      wifiCheckPoints++;
      displayManager->show();
      delay(50);
    }
  }
}

void time_sync_anim(int x, int y)
{
  for (int i = 0; i < 4; i++)
  {
    displayManager->ShowMessage("SYNC", 5, displayManager->Color(255, 255, 255));

    displayManager->drawPixel(x + i, y, (uint32_t)0x22ff);
    displayManager->show();
    delay(100);
    displayManager->clear();
  }
}

void time_sync_anim_v2()
{
  const int dot_x = 27, dot_y = 5;
  displayManager->clear();
  displayManager->DrawIcon(0, 0, &img_info_note);

  for (int i = 0; i < 4; i++)
  {
    displayManager->Print("SYNC", 10, 5, CRGB::White);

    displayManager->drawPixel(dot_x + i, dot_y, (uint32_t)0x22ff);
    displayManager->show();
    delay(100);
    displayManager->drawPixel(dot_x + i, dot_y, displayManager->Color24to16((uint32_t)CRGB::Black));
  }
}

void anim_time(char *tmp, bool flag_show_colon)
{
  displayManager->clear();

  displayManager->setTextColor(displayManager->Color24to16(CRGB::Purple));
  displayManager->setCursor(2, 5);
  displayManager->print(tmp);
  if (flag_show_colon)
  {
    displayManager->setTextColor(displayManager->Color24to16(CRGB::White));
    displayManager->setCursor(2, 5);
    displayManager->print("    :    :");
  }

  displayManager->show();
}

void anim_date(char *date, char *week)
{
  displayManager->clear();

  char *tmp[3] = {date, "-    -", week};
  int offsets[3] = {0, 16, 40}; // 偏移量
  CRGB colors[3] = {CRGB::LightSkyBlue, CRGB::White, CRGB::LightCoral};
  displayManager->PrintAnimation(tmp,
                                 DISPLAY_CONTENT_X_START_DEFAULT, DISPLAY_CONTENT_X_END_DEFAULT,
                                 &anim_cont_x_default, offsets, colors, 3);

  displayManager->DrawIconAnimation(0, (int16_t *)&anim_icon_y_default, DISPLAY_ICON_Y_END_DEFAULT, &img_date);

  displayManager->show();
}

// 代码雨配置 8列为一组 共四组
int columnIndex[8];
int stepIndex[8];
int glow[8];
bool Running[8] = {false, false, false, false, false, false, false, false};
int stepsTillNext[8] = {0, 6, 2, 11, 4, 10, 7, 1};
int colorh = 120; // 默认绿色
void anim_raining_code()
{
  static uint8_t hue = 0;
  displayManager->clear();

  for (int i = 0; i < 8; i++)
  {
    // 增加生成概率到30%
    if (!Running[i] && random(100) > 70)
    {
      columnIndex[i] = random(i * 4, (i + 1) * 4);
      stepIndex[i] = 0;
      Running[i] = true;
      glow[i] = random(160, 255); // 提高初始亮度
    }

    // 延长雨滴到5个像素
    if (Running[i])
    {
      for (int j = 0; j < 5; j++)
      {
        int yPos = stepIndex[i] - j;
        if (yPos >= 0 && yPos < MATRIX_HEIGHT)
        {
          CRGB color = CHSV(colorh + j * 20, 255, glow[i] / (j + 1)); // 增加色相偏移
          displayManager->drawPixel(columnIndex[i], yPos, color);
        }
      }

      stepIndex[i]++;
      glow[i] = qsub8(glow[i], 10); // 减缓亮度衰减

      // 延长下落距离
      if (stepIndex[i] >= MATRIX_HEIGHT + 5)
      {
        Running[i] = false;
      }
    }
  }

  displayManager->show();
  colorh += 5; // 加快色相变化
}

uint8_t sandPile[8] = {0};               // 每列沙堆高度（0-24）
const CRGB SAND_COLOR = CRGB::Goldenrod; // 沙粒颜色
void timer_state_init(timer_state_t *timer, int duration)
{
  timer->startTime = millis();
  timer->duration = duration;
  timer->remaining = duration;
  for (uint8_t x = 0; x < 8; x++)
    sandPile[x] = 0; // 清空每列沙堆高度
  for (uint8_t i = 0; i < MAX_SAND_PARTICLES; i++)
    timer->fallingSand[i].y = -1; // 初始未激活
}

bool anim_timer(timer_state_t *timer)
{
  displayManager->setRotation(1);
  displayManager->clear();
  bool finished = false;

  if (timer->remaining > 0)
  {
    // 更新剩余时间
    timer->remaining = timer->duration - (millis() - timer->startTime) / 1000;

    // 1. 处理下落中的沙粒
    for (uint8_t i = 0; i < MAX_SAND_PARTICLES; i++)
    {
      if (timer->fallingSand[i].y >= 0)
      {
        // 保存旧位置到轨迹（从后往前覆盖）
        for (uint8_t t = 2; t > 0; t--)
          timer->fallingSand[i].trail[t] = timer->fallingSand[i].trail[t - 1];
        timer->fallingSand[i].trail[0] = timer->fallingSand[i].y; // 记录当前旧Y值
        // 沙粒下落（每帧Y+1）
        timer->fallingSand[i].y++;
        // 检查是否到达沙堆顶部
        if (timer->fallingSand[i].y >= 31 - sandPile[timer->fallingSand[i].x])
        {
          // 堆积到沙堆
          if (sandPile[timer->fallingSand[i].x] < 24)
          {
            sandPile[timer->fallingSand[i].x]++;
          }
          // 清空轨迹防止残留
          for (uint8_t t = 0; t < 3; t++)
            timer->fallingSand[i].trail[t] = 0;
          timer->fallingSand[i].y = -1; // 标记为未激活
        }
        else
        {
          // 绘制当前位置（全亮度）
          displayManager->drawPixel(timer->fallingSand[i].x, timer->fallingSand[i].y, SAND_COLOR);
          // 绘制拖影（亮度递减）
          for (uint8_t t = 0; t < 3; t++)
          {
            if (timer->fallingSand[i].trail[t] > 0)
            {
              CRGB trailColor = SAND_COLOR;
              trailColor.nscale8_video(255 - t * 112); // 第1级50%亮度（255-64=191），第2级25%（255-128=127）
              displayManager->drawPixel(timer->fallingSand[i].x, timer->fallingSand[i].trail[t],
                                        displayManager->Color24to16((uint32_t)trailColor));
            }
          }
        }
      }
    }

    // 2. 生成新沙粒（8%概率生成）
    // note：影响到沙堆堆积的速度
    if (random(100) < 8)
    {
      for (uint8_t i = 0; i < MAX_SAND_PARTICLES; i++)
      {
        if (timer->fallingSand[i].y == -1)
        {
          timer->fallingSand[i].x = random(8); // 随机选择列
          timer->fallingSand[i].y = 8;         // 从Y=8开始下落（屏幕顶部向下8像素）
          break;
        }
      }
    }

    // 3. 绘制沙堆（保持原有逻辑）
    for (uint8_t x = 0; x < 8; x++)
    {
      for (uint8_t y = 0; y < sandPile[x]; y++)
      {
        displayManager->drawPixel(x, 31 - y, SAND_COLOR);
      }
    }

    // 上部分8x8倒计时显示（剩余≤10秒时）
    if (timer->remaining > 0 && timer->remaining < 10)
    {
      // 每秒闪烁（500ms周期）
      bool blink = (millis() / 500) % 2 == 0;
      if (blink)
      {
        displayManager->setTextColor(displayManager->Color24to16(CRGB::Red));
        displayManager->setCursor(2, 6); // 上部分中心位置
        char tmp[6] = {};
        sprintf(tmp, "%d", timer->remaining); // 显示剩余时间[0,9]
        displayManager->print(tmp);
      }
    }
    else
    {
      displayManager->DrawIcon(0, 0, &img_timer);
    }
  }
  else
  {
    // 非运行状态：初始/结束状态
    // 结束时全屏闪烁（红/白交替4次）
    // note这里不初始化也不影响，因为交替闪烁就2个页面
    static int flashCount = 0;
    // if (flashCount < 8)
    // {
    CRGB color = (flashCount % 2 == 0) ? CRGB::Red : CRGB::White;
    // note：奇怪这里不加强制类型转化uint32_t会编译错误
    displayManager->fillScreen(displayManager->Color24to16((uint32_t)color));
    flashCount++;
    // }
    // else
    // {
    //   // 闪烁结束后重置状态
    //   flashCount = 0;
    //   timer_state_init(timer, timer->duration);
    // }
    finished = true;
  }

  displayManager->show();
  displayManager->setRotation(0); // 每次显示完都要重置，防止影响其他显示
  return finished;
}

void anim_weather(weather_t *we, int idx, bool init)
{
  if (init)
  {
    anim_init();
  }

  displayManager->clear();

  char tmp[40] = {0};
  sprintf(tmp, "%s-%sC", we->temp_low, we->temp_high);
  // displayManager->PrintAnimation(tmp,
  //                                DISPLAY_CONTENT_X_START_DEFAULT, DISPLAY_CONTENT_X_END_DEFAULT,
  //                                &show_weather_anim_ctx_x, CRGB::White);
  displayManager->Print(tmp, 9, 5, CRGB::White);

  // 用像素点表明是第几天的天气预报
  displayManager->drawFastHLine(14 + idx * 5, 7, idx + 1, displayManager->Color24to16(CRGB::Purple));

  displayManager->DrawIconAnimation(0,
                                    (int16_t *)&anim_icon_y_default, DISPLAY_ICON_Y_END_DEFAULT,
                                    get_image_by_code(we->code));

  displayManager->show();
}

void anim_aht20(float temp, float humidity)
{
  displayManager->clear();

  CRGB temp_color;
  if (temp <= 0)
    temp_color = CRGB::LightSkyBlue;
  else if (temp < 10)
    temp_color = CRGB::LimeGreen;
  else if (temp < 20)
    temp_color = CRGB::MediumPurple;
  else if (temp < 29)
    temp_color = CRGB::LightSeaGreen;
  else
    temp_color = CRGB::Red;

  char tmp1[8] = {};
  sprintf(tmp1, "%.1fC", temp);

  CRGB hum_color;
  if (humidity < 40)
    hum_color = CRGB::Red;
  else if (humidity < 60)
    hum_color = CRGB::Orange;
  else if (humidity < 80)
    hum_color = CRGB::Olive;
  else
    hum_color = CRGB::Snow;
  char tmp2[8] = {};
  sprintf(tmp2, "%.1f%%", humidity);

  char *tmp[2] = {tmp1, tmp2};
  int offsets[2] = {0, 20}; // 偏移量
  CRGB colors[2] = {temp_color, hum_color};
  displayManager->PrintAnimation(tmp,
                                 DISPLAY_CONTENT_X_START_DEFAULT, DISPLAY_CONTENT_X_END_DEFAULT,
                                 &anim_cont_x_default, offsets, colors, 2);

  displayManager->DrawIconAnimation(0, (int16_t *)&anim_icon_y_default, DISPLAY_ICON_Y_END_DEFAULT, &img_temp_hum);

  displayManager->show();
}

void anim_init()
{
  // 共用一个x、y
  anim_cont_x_default = DISPLAY_CONTENT_X_START_DEFAULT;
  anim_icon_y_default = DISPLAY_ICON_Y_START_DEFAULT;
}